package io.zpy.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SimplePropertyPreFilter;
import com.google.common.collect.Lists;
import io.zpy.entity.PushOrder;
import io.zpy.quartz.ScheduleJob;
import io.zpy.utils.MD5;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Utils {

    //从.json文件获取json字符串
    public static String getJson(String filePath) {
        String jsonStr = "";
        try {
            File file = new File(filePath);
            FileReader fileReader = new FileReader(file);
            Reader reader = new InputStreamReader(new FileInputStream(file), "Utf-8");
            int ch = 0;
            StringBuffer sb = new StringBuffer();
            while ((ch = reader.read()) != -1) {
                sb.append((char) ch);
            }
            fileReader.close();
            reader.close();
            jsonStr = sb.toString();
            return jsonStr;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 处理json字符串返回需要的信息
     *
     * @param json
     * @return
     */
    public static String jsonToString(String json) {
        String s = "";
        JSONObject jsonObject = JSONObject.parseObject(json);
        JSONArray jss = jsonObject.getJSONArray("results");
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < jss.size(); i++) {
            JSONObject temp = jss.getJSONObject(i);
            String str = (String) temp.get("title") + "/" + temp.get("link") + "；";
            sb.append(str);

        }
        s = sb.toString().substring(0, sb.toString().length() - 1);

        return s;
    }

    /**
     * 日期转换
     *
     * @return
     */
    public static String getDateFormat() {
        Date date = new Date();
        SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sd.format(date);
    }

    /**
     * 日期转换
     *
     * @return
     */
    public static String getDateFormat2() {
        Date date = new Date();
        SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd");
        return sd.format(date);
    }

    /**
     * 时间字符串str加上时间time后返回一个新的Date
     *
     * @param str
     * @param time
     * @return
     * @throws Exception
     */
    public static Date stringToDate(String str, long time) throws Exception {
        SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date currentTime = sd.parse(str);
        long times = currentTime.getTime();
        times += time;
        Date da = new Date(times);

        return da;
    }

    /**
     * 过滤不需要的字段
     *
     * @param object
     * @return
     */
    public static JSONObject formatJson(JSONObject object) {

        SimplePropertyPreFilter propertyPreFilter = new SimplePropertyPreFilter();
        List<String> excludeFields = Lists.newArrayList();
        //要过滤的字段名称 ****
        excludeFields.add("cronExpression");
        excludeFields.add("jobName");
        excludeFields.add("updateDate");
        excludeFields.add("jobGroup");
        excludeFields.add("createDate");
        propertyPreFilter.getExcludes().addAll(excludeFields);
        String json = JSON.toJSONString(object, propertyPreFilter);
        return JSONObject.parseObject(json);
    }

    /**
     * 验证邮箱地址的合理性
     *
     * @param str 邮箱地址
     * @return
     */
    public static boolean isMail(String str) {
        Pattern p = null;
        Matcher m = null;
        boolean isMatch = false;
        // 制定验证条件
        String regex = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";

        p = Pattern.compile(regex);
        m = p.matcher(str);
        isMatch = m.matches();
        return isMatch;
    }

    /**
     * 功能描述：返回年
     *
     * @param date 日期
     * @return
     */
    public static int getYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.YEAR);
    }

    /**
     * 功能描述：返回月
     *
     * @param date Date 日期
     * @return 返回月份
     */
    public static int getMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MONTH) + 1;
    }

    /**
     * 功能描述：返回日期
     *
     * @param date Date 日期
     * @return 返回日份
     */
    public static int getDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 功能描述：返回小时
     *
     * @param date 日期
     * @return 返回小时
     */
    public static int getHour(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.HOUR_OF_DAY);
    }

    /**
     * 功能描述：返回分
     *
     * @param date 日期
     * @return 返回分钟
     */
    public static int getMinute(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MINUTE);
    }

    /**
     * 返回秒钟
     *
     * @param date Date 日期
     * @return 返回秒钟
     */
    public static int getSecond(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.SECOND);
    }

    /**
     * 功能描述：返回毫
     *
     * @param date 日期
     * @return 返回毫
     */
    public static long getMillis(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getTimeInMillis();
    }

    /**
     * 根据传入日期得到所在周周一日期
     *
     * @return
     */
    public static String getWeekMonday(String str) {
        SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sd1 = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal = new GregorianCalendar();
        Date first = null;
        Date date = null;
        try {
            date = sd.parse(str);
            cal.setFirstDayOfWeek(Calendar.MONDAY);
            cal.setTime(date);
            cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
            first = cal.getTime();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
        return sd1.format(first);
    }

    /**
     * 根据传入日期得到所在周周日日期
     *
     * @return
     */
    public static String getWeekSunday(String str) {
        SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sd1 = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal = new GregorianCalendar();
        Date date = null;
        Date last = null;
        try {
            date = sd.parse(str);
            cal.setFirstDayOfWeek(Calendar.MONDAY);
            cal.setTime(date);
            cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek() + 6);
            last = cal.getTime();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
        return sd1.format(last);
    }

    /**
     * 初始化定时类参数
     *
     * @param po   订单类
     * @param flag 用来区分新增还是更新，“1”新增；“2”更新；“3”服务重启
     * @return
     * @throws Exception
     */
    public static ScheduleJob initScheduleJob(PushOrder po, String flag) throws Exception {
        ScheduleJob job = new ScheduleJob();
        if (flag.equals("1")) {
            job.setCreateDate(po.getCreateDate());
        } else if (flag.equals("2")) {
            job.setPid(po.getPid());
            job.setUpdateDate(po.getUpdateDate());
        } else if (flag.equals("3")) {
            job.setUpdateDate(Utils.getDateFormat());
            job.setPid(po.getPid());
        }
        job.setJobName(po.getJobName());
        job.setJobGroup(po.getJobGroup());
        job.setFlag(flag);//区分来源
        job.setKeywords(po.getKeywords());
        job.setToAddress(po.getToAddress());
        job.setFrequency(po.getFrequency());
        job.setTrackAmount(po.getTrackAmount());
        job.setUid(po.getUid());
        setExpression(po, job);
        return job;
    }

    /**
     * Expression  cron表达式设置
     *
     * @param po
     * @param job
     * @throws Exception
     */
    public static void setExpression(PushOrder po, ScheduleJob job) throws Exception {
        //为了防止同一时间发送邮件请求过多，设置多个时间段
        Integer num = getRandNum(3);
        // cron表达式
        if (po.getFrequency().equals("1")) {//追踪频率选择每天
            if (num == 1) {
                job.setCronExpression("0 0 18 * * ?");//每天下午6点触发
            } else if (num == 2) {
                job.setCronExpression("0 0 1 * * ?");//每天凌晨1点触发
            } else if (num == 3) {
                job.setCronExpression("0 0 3 * * ?");//每天凌晨3点触发
            }
//            job.setCronExpression("0/10 * * * * ?");//10秒钟执行一次
        } else if (po.getFrequency().equals("2")) {//每周  2020-05-20 16:35:54
            if (num == 1) {
                job.setCronExpression("0 0 18 ? * SUN");//每周日下午6点触发
            } else if (num == 2) {
                job.setCronExpression("0 0 1 ? * SUN");//每周日凌晨1点触发
            } else if (num == 3) {
                job.setCronExpression("0 0 3 ? * SUN");//每周日凌晨3点触发
            }
//            job.setCronExpression("0/20 * * * * ?");//20秒钟执行一次
        } else if (po.getFrequency().equals("3")) {//无要求  无要求就只给他发一次
            Date d = stringToDate(Utils.getDateFormat(), 10 * 6000 * 60);//1小时后给发
            job.setCronExpression(Utils.getSecond(d) + " " + Utils.getMinute(d) + " " + Utils.getHour(d) + " " + Utils.getDay(d) + " " + Utils.getMonth(d) + " ? " + Utils.getYear(d));//30分钟后触发
        }
    }

    /**
     * 生成随机数
     *
     * @param count 随机数生成范围 例输入3 则生成1，2，3三个随机数
     * @return
     */
    public static Integer getRandNum(int count) {
        Random rand = new Random();
        Integer num = rand.nextInt(count) + 1;
        return num;
    }

    /**
     * 加密，返回的是加密后的字符串
     *
     * @param message
     * @param key
     * @return
     * @throws Exception
     */
    public static String encrypt2(String message, String key) {
        String jiami = "";
        String a = "";
        try {
            jiami = java.net.URLEncoder.encode(message, "utf-8")
                    .toLowerCase();
            a = toHexString(encrypt(jiami, key)).toUpperCase();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return a;
    }

    /**
     * 加密
     *
     * @param message
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] encrypt(String message, String key) throws Exception {
        //加密是八位密钥。C#是取MD5加密后的前8位进行的，这里我们也要这样做一下
        key = MD5.md5Password(key).substring(0, 8).toUpperCase();

        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
        IvParameterSpec iv = new IvParameterSpec(key.getBytes("UTF-8"));
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
        return cipher.doFinal(message.getBytes("UTF-8"));
    }

    public static String toHexString(byte b[]) {
        StringBuffer hexString = new StringBuffer();
        for (int i = 0; i < b.length; i++) {
            String plainText = Integer.toHexString(0xff & b[i]);
            if (plainText.length() < 2) {
                plainText = "0" + plainText;
            }
            hexString.append(plainText);
        }

        return hexString.toString();
    }
}